﻿using System;
using System.IO;
using System.Windows.Forms;
using SharpCompress.Common;
using SharpCompress.Reader;
using System.Drawing;
using System.Threading;
using System.Net;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace GWIUpdater
{
    public partial class Updater : Form
    {
        [DllImport("wininet.dll", EntryPoint = "InternetGetConnectedState")]
        public extern static bool InternetGetConnectedState(out int conState, int reder);

        /// <summary>
        /// 配置文件路径及文件名
        /// </summary>
        private string configPath = Application.StartupPath + @"/config/GWIUpdater.ini";

        private string tempPath = Application.StartupPath + @"/temp";

        private System.Windows.Forms.Label lMsg;

        private VersionList versionList;

        private string current;

        private WebClient client;

        // private string updaterName = Process.GetCurrentProcess().MainModule.ModuleName;//更新器文件名
        private string updaterName = Application.ExecutablePath;//更新器文件名(路径加文件名)

        private string updaterName_temp;//更新器临时文件名

        public Updater()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 修改更新器的文件名
        /// </summary>
        private void ChangeUpdaterName()
        {
            //MessageBox.Show(updaterName);
            updaterName_temp = "GWIUpdater.running.exe";
            //File.Move (updaterName, Application.StartupPath + "/" + updaterName_temp,null);
            File.Move(updaterName, Application.StartupPath + "/" + updaterName_temp);
            //Directory.Move(updaterName, Application.StartupPath + "/" + updaterName_temp);
            //MessageBox.Show(Application.StartupPath + "/" + updaterName_temp);
        }
        /// <summary>
        ///更新更新器本身
        /// </summary>
        private void UpdateSelf()
        {
            if (File.Exists(updaterName))
            {
                Directory.Delete(Application.StartupPath + "/" + updaterName_temp);
                Process myNewProcess = new Process();

                myNewProcess.StartInfo.FileName = updaterName; //设置要启动的程序

                myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; //设置工作目录

                myNewProcess.Start(); //准备重启程序
            }
            else
            {
                Directory.Move(Application.StartupPath + "/" + updaterName_temp, updaterName);
            }

            //Application.Exit(); //退出当前程序集
        }
        private void Updater_Load(object sender, EventArgs e)
        {
            ChangeUpdaterName();
            SetUI();
            CreateMsgLabel();

            if (!Directory.Exists(tempPath))
            {
                Directory.CreateDirectory(tempPath);
            }

            client = new WebClient();

            Thread tUpdate = new Thread(StartUpdate);
            tUpdate.IsBackground = true;
            tUpdate.Start();
        }
        private void CreateMsgLabel()
        {
            lMsg = new System.Windows.Forms.Label();

            lMsg.BackColor = Color.Transparent;
            lMsg.ForeColor = Color.Red;
            lMsg.Font = new Font(new FontFamily("黑体"), 24, FontStyle.Bold);
            lMsg.Height = 44;
            lMsg.Width = Width;
            lMsg.TextAlign = ContentAlignment.MiddleCenter;
            lMsg.Location = new Point(0, (Height - lMsg.Height) / 2);
            Controls.Add(lMsg);
        }

        /// <summary>
        /// 设置程序ui
        /// </summary>
        private void SetUI()
        {
            Width = int.Parse(Ini.Read(configPath, "UI", "width"));
            Height = int.Parse(Ini.Read(configPath, "UI", "height"));
            BackgroundImage = Image.FromFile("config/GWIUpdater.jpg");
        }



        private delegate void CrossSetMsgHandler(string msg);
        private void SetMsg(string msg)
        {
            if (this.InvokeRequired)
            {
                CrossSetMsgHandler handler = new CrossSetMsgHandler(SetMsg);
                Invoke(handler, msg);
            }
            else
            {
                lMsg.Text = msg;
            }
        }


        /// <summary>
        /// 检测更新
        /// </summary>
        private void CheckUpdate()
        {
            versionList = new VersionList();
            string source = Ini.Read(configPath, "Updater", "source");

            client.DownloadFile(source + @"/versionlist.txt", tempPath + @"/versionlist.txt");
            string[] allLines = File.ReadAllLines(tempPath + @"/versionlist.txt");
            string[] attr;
            current = Ini.Read(configPath, "Updater", "current");
            //versionList.IndexOf(
            if (current == "0")
            {
                foreach (string x in allLines)
                {
                    if (x.Trim() != string.Empty)
                    {
                        attr = x.Split('|');
                        versionList.Add(new Version(attr[0], attr[1], attr[2], attr[3]));
                    }
                }
            }
            else
            {
                bool startAdd = false;
                foreach (string x in allLines)
                {
                    if (x.Trim() != string.Empty)
                    {
                        attr = x.Split('|');
                        if (startAdd)
                        {
                            versionList.Add(new Version(attr[0], attr[1], attr[2], attr[3]));
                        }
                        else if (attr[0] == current)
                        {
                            startAdd = true;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 下载更新文件并比对md5
        /// </summary>
        private void DownloadPatch()
        {
            string source = Ini.Read(configPath, "Updater", "source");
            string patchCount = versionList.Count.ToString();
            int index = 1;
            foreach (Version x in versionList)
            {
                SetMsg("正在下载更新，" + index.ToString() + "/" + patchCount + "(" + x.Comment + ")");
                do
                {

                    client.DownloadFile(source + "/" + x.Name, tempPath + @"/" + x.Name);
                } while (Compress.GetMD5(tempPath + @"/" + x.Name).ToLower() != x.MD5.ToLower());

                index++;
            }
        }

        private void InstallPatch()
        {
            string patchCount = versionList.Count.ToString();
            string target;
            int index = 1;
            foreach (Version x in versionList)
            {
                SetMsg("正在安装更新，" + index.ToString() + "/" + patchCount);
                target = Ini.Read(configPath, "Updater", x.Target);

                Compress.Extract(tempPath + @"/" + x.Name, target);
                //
                index++;
            }
        }

        private void FinishUpdate()
        {

            if (Directory.Exists(tempPath))
            {
                Directory.Delete(tempPath, true);
            }
            Process p = new Process();
            p.StartInfo.FileName = Ini.Read(configPath, "Updater", "exec");
            p.StartInfo.WorkingDirectory = Ini.Read(configPath, "Updater", "exepath");
            p.Start();
            SetMsg("更新完成");
            Application.Exit();
        }

        private void WaitActiveNetwork()
        {
            int conState = 0;
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                while (true)
                {
                    if (InternetGetConnectedState(out conState, 0))
                    {
                        break;
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
        }

        private void StartUpdate()
        {
            try
            {
                SetMsg("等待网络");
                WaitActiveNetwork();
                SetMsg("正在检查更新");
                CheckUpdate();
                if (versionList.Count > 0)
                {
                    DownloadPatch();
                    InstallPatch();

                    current = versionList[versionList.Count - 1].Name;
                    Ini.Write(configPath, "Updater", "current", current);
                }
                UpdateSelf();
                FinishUpdate();
            }
            catch (Exception ex)
            {
                SetMsg(ex.Message);
            }
        }
        /// <summary>
        /// 按下esc键关闭程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Updater_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Application.Exit();
            }
        }

        /// <summary>
        /// 双击关闭程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Updater_DoubleClick(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void Updater_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!File.Exists(updaterName))
            {
                Directory.Move(Application.StartupPath + "/" + updaterName_temp, updaterName);
            }
        }
    }
}
